package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;


    @Override
    @Cacheable(value = "resourceList",key = "#resourceDto.hashCode()")
    public List<ResourceVo> findList(ResourceDto resourceDto) {
        log.error("findList数据从MySQL中获取");
        return resourceMapper.findList(resourceDto);
    }

    @Override
    @Cacheable(value = "resourceTree",key = "#resourceDto.hashCode()")
    public TreeVo tree(ResourceDto resourceDto) {
        log.error("tree数据从MySQL中获取");
        // 一次性把数据先查询出来
        List<ResourceVo> resourceVoList = resourceMapper.findList(resourceDto);
        TreeVo treeVo = TreeVo.builder().items(new ArrayList<>()).build();

        // 构建根
        TreeItemVo rootItemVo = TreeItemVo.builder().id(SuperConstant.ROOT_PARENT_ID).label("智慧养老院").children(new ArrayList<>()).build();
        treeVo.getItems().add(rootItemVo);

        // // 构建一级
        // for (ResourceVo vo1 : resourceVoList) {
        //     if (rootItemVo.getId().equals(vo1.getParentResourceNo())){
        //         TreeItemVo itemVo1 = TreeItemVo.builder().id(vo1.getResourceNo()).label(vo1.getResourceName()).children(new ArrayList<>()).build();
        //         rootItemVo.getChildren().add(itemVo1);
        //// 构建二级
        //         for (ResourceVo vo2 : resourceVoList) {
        //             if(itemVo1.getId().equals(vo2.getParentResourceNo())){
        //                 TreeItemVo itemVo2 = TreeItemVo.builder().id(vo2.getResourceNo()).label(vo2.getResourceName()).children(new ArrayList<>()).build();
        //                 itemVo1.getChildren().add(itemVo2);
        //
        //// 构建三级
        //                 for (ResourceVo vo3 : resourceVoList) {
        //                     if(itemVo2.getId().equals(vo3.getParentResourceNo())){
        //                         TreeItemVo itemVo3 = TreeItemVo.builder().id(vo3.getResourceNo()).label(vo3.getResourceName()).children(new ArrayList<>()).build();
        //                         itemVo2.getChildren().add(itemVo3);
        //                     }
        //                 }
        //             }
        //         }
        //     }
        //
        // }

        // 递归

        recursionTreeItem(rootItemVo,resourceVoList);


        return treeVo;
    }

    // 递归构建树形
    private void recursionTreeItem(TreeItemVo rootItemVo, List<ResourceVo> resourceVoList) {

        for (ResourceVo vo : resourceVoList) {
            if(rootItemVo.getId().equals(vo.getParentResourceNo())  && vo.getResourceType().equals(SuperConstant.MENU)){
                TreeItemVo itemVo = TreeItemVo.builder().id(vo.getResourceNo()).label(vo.getResourceName()).children(new ArrayList<>()).build();
                rootItemVo.getChildren().add(itemVo);
                recursionTreeItem(itemVo,resourceVoList);
            }
        }

    }

    @Override
    // @CacheEvict(value ="resourceTree",allEntries = true )
    @Caching(evict = {@CacheEvict(value ="resourceTree",allEntries = true ),
                @CacheEvict(value ="resourceList",allEntries = true )})
    public void add(ResourceDto resourceDto) {
        // 把DTO转成实体类

        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        // 查询父资源
        Resource parentResource = resourceMapper.selectByResourceNo(resourceDto.getParentResourceNo());
        resource.setDataState(parentResource.getDataState());
        boolean isMenu = true;

        if(resourceDto.getResourceType().equals(SuperConstant.BUTTON)){
            isMenu  = false; ///如果是按钮就忽略层级
        }

        // 创建编号
        String resourceNo = createResourceNo(resource.getParentResourceNo(), isMenu);//如果是按钮就不用在乎层级
        resource.setResourceNo(resourceNo);
        resourceMapper.insert(resource);

    }



    /**
     * 创建资源的编号
     * @param parentResourceNo
     * @return
     */
    private String createResourceNo(String parentResourceNo,boolean isMenu) {

        //判断资源编号是否大于三级
        //100 001 000 000 000
        //100 001 001 000 000
        //100 001 001 001 000
        //100 001 001 001 001 001
        if (isMenu && NoProcessing.processString(parentResourceNo).length() / 3 >= 5) {
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }

        //根据父资源编号查询子资源
        ResourceDto dto = ResourceDto.builder().parentResourceNo(parentResourceNo).build();
        List<ResourceVo> resources = resourceMapper.findList(dto);
        if (EmptyUtil.isNullOrEmpty(resources)) {
            //无下属节点，创建新的节点编号  100 001 001 001 000--->100 001 001 001 001
            return NoProcessing.createNo(parentResourceNo, false);
        } else {
            //有下属节点，在已有的节点上追加
            //先获取已有节点的最大值--100001003000000
            Long maxNo = resources.stream().map(resource -> {
                return Long.valueOf(resource.getResourceNo());
            }).max(Comparator.comparing(i -> i)).get();
            // 100,001,004,000,000
            return NoProcessing.createNo(String.valueOf(maxNo), true);
        }
    }

    @Override // 获取当前登录人的菜单
    public List<MenuVo> menus(Long userId) {
        List<MenuVo> menuVoList = resourceMapper.selectMenusByUserId(userId);
        // 根据menuVoList中的ParentResourceNo分组
        Map<String, List<MenuVo>> menuVoMap = menuVoList.stream().collect(Collectors.groupingBy(MenuVo::getParentResourceNo));


        // 获取每个菜单的子菜单
        for (MenuVo menuVo : menuVoList) {
            // menuVo.getResourceNo()
            // select * from sys_resurce where parent_resource_no = menuVo.getResourceNo()
            menuVo.setChildren(menuVoMap.get(menuVo.getResourceNo()));
            menuVo.setMeta(MenuMetaVo.builder().title(menuVo.getName()).build());
        }

        return  menuVoMap.get(SuperConstant.ROOT_PARENT_ID);

    }

}
